﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Globalization;
using JSC.Portal.Module;
using JSC.Portal.Web.Models;
using JSC.Portal.Entities;
using System.Web;
using JSC.Portal.Entities.Interfaces;
using System.Web.UI.WebControls;
using System.Security.Principal;
using System.Linq.Expressions;
using System.Reflection;

namespace JSC.Portal.Web.Helper
{
    public static class UIHelper
    {
        public static string GetPortalLanguage(this HtmlHelper htmlHelper)
        {
            return htmlHelper.ViewContext.HttpContext.Request.Cookies["JSC.Culture"].Value;
        }

        public static string GetShortPortalLanguage(this HtmlHelper htmlHelper)
        {
            return GetPortalLanguage(htmlHelper).Substring(0, 2);
        }

        public static void RenderModuleControls(this HtmlHelper htmlHelper, string placeholder)
        {
            DesignPageViewData dpvd = htmlHelper.ViewData.Model as DesignPageViewData;
            if (dpvd != null)
            {
                RenderDesignModuleControls(htmlHelper, placeholder, dpvd);
                return;
            }
            TemplatedViewData tvd = htmlHelper.ViewData.Model as TemplatedViewData;
            if (tvd != null)
            {
                RenderViewModuleControls(htmlHelper, placeholder, tvd);
                return;
            }            
        }

        private static void RenderDesignModuleControls(HtmlHelper htmlHelper, string placeholder, DesignPageViewData data)
        {
            IDictionary<Section, IList<IModuleBase>> result = new Dictionary<Section, IList<IModuleBase>>();
            IList<IModuleBase> allmodules = data.Modules.FindAll(m => m.Placeholder == placeholder);
            ViewDataDictionary vdd = new ViewDataDictionary();
            vdd["Placeholder"] = placeholder;
            htmlHelper.RenderPartial("ModulePositionDesignControl", allmodules, vdd);
        }

        private static void RenderViewModuleControls(this HtmlHelper htmlHelper, string placeholder, TemplatedViewData data)
        {
            IIdentity identity = htmlHelper.ViewContext.HttpContext.User.Identity;
            foreach(IModuleBase module in data.Modules.Where(m => m.Placeholder == placeholder && m.Section.ViewAllowed(identity)))
            {
                if (module.Section.ShowName)
                    htmlHelper.RenderPartial("SectionViewControl", module.Section);

                RenderModuleControl(htmlHelper, module.ControllerName, module.ViewName, module.Section.Id);

                //string loc = string.Format(@"~/Modules/{0}/Views/{1}.ascx", module.ControllerName, module.ViewName);
                //htmlHelper.RenderPartial(loc, module.Data);
            }
        }

        public delegate bool delTypeCheck(Type type);

        public static IEnumerable<T> GetControlsOfType<T>(this Control ctrMain, delTypeCheck IsExemptCheck) where T : class
        {
            // Determine the Type we need to look out for
            Type searchType = typeof(T);

            foreach (Control c in ctrMain.Controls)
            {
                // If user wants to exclude certain types then a call-back has been given
                // So call it with the current control-type and check if it is exempt.
                if (IsExemptCheck != null && IsExemptCheck(c.GetType()))
                    continue;   // the type of c is exempt so continue.

                // If a match is found then yield this item back directly    
                if (c is T) yield return (c as T);

                // if you want to search for specific Types only (and NOT derived types) then
                // uncomment the following lines (and comment out the above statement).
                //if (c.GetType().Equals(searchType))
                //    yield return (c as T);

                // If the control hosts other controls then recursively call this function again.
                if (c.Controls.Count > 0)
                    foreach (T t in GetControlsOfType<T>(c, IsExemptCheck))
                        yield return t;
            }
        }

        /// <summary>
        /// Fckeditor’sHTMLHelper
        /// </summary>
        /// <param name="u"></param>
        /// <param name="name">Html name</param>
        /// <param name="value">Content</param>
        /// <returns></returns>
        public static string FckTextBox(this HtmlHelper u, string name, string value)
        {
            if (value == null)
            {
                value = Convert.ToString(u.ViewDataContainer.ViewData[name], CultureInfo.InvariantCulture);
            }

            return string.Format(@"<textarea name=""{0}"" id=""{0}"" rows=""50"" cols=""80"" style=""width:100%; height: 600px"">{1}</textarea>
                <script type=""text/javascript"">
                    var oFCKeditor = new FCKeditor('{0}') ;
                    //oFCKeditor.BasePath    = sBasePath ;
                oFCKeditor.Height=400;
                    oFCKeditor.ReplaceTextarea() ;
                </script>
                ", name, value);
        }

        public static string CheckBox(this HtmlHelper helper, string name, string value, bool isChecked)
        {
            return string.Format(@"<input type=""checkbox"" id=""{0}"" name=""{0}"" value=""{1}"" {2} />", name, value, isChecked ? @"checked=""checked""" : null);
        }

        public static string RenderTreeView<T>(this HtmlHelper htmlHelper, IEnumerable<T> rootLocations, Func<T, string> locationRenderer)
            where T : IComposite<T>
        {
            return new TreeViewRenderer<T>(rootLocations, locationRenderer).Render();
        }

        public static string RenderTreeView<T>(this HtmlHelper htmlHelper, T root, Func<T, string> locationRenderer)
            where T : IComposite<T>
        {
            IList<T> rootlist = new List<T>();
            rootlist.Add(root);
            return RenderTreeView<T>(htmlHelper, rootlist, locationRenderer);
        }

        public static string ImageButton(this HtmlHelper htmlHelper, string action, string controller, object values, string cssClass, string text, string imageLocation)
        {
            System.Web.Mvc.UrlHelper u = new System.Web.Mvc.UrlHelper(htmlHelper.ViewContext.RequestContext);
            return string.Format(@"<a href=""{0}"" class=""{1}""><img src=""{2}""/>{3}</a>",
                u.Action(action, controller, values), cssClass, VirtualPathUtility.ToAbsolute(imageLocation), text);        
        }

        public static string TextBox(this HtmlHelper htmlHelper, string name, string cssClass)
        {
            return string.Format(@"<input type=""text"" id=""{0}"" name=""{0}"" class=""{1}"" />", name, cssClass);
        }

        public static string RenderModuleControl(this HtmlHelper helper, string controller, string viewname, int sectionid)
        {
            DefaultControllerFactory dcf = new DefaultControllerFactory();
            Controller c = (Controller)dcf.CreateController(helper.ViewContext.RequestContext, controller);
            //ControllerContext cc = new ControllerContext(helper.ViewContext.HttpContext, helper.ViewContext.RouteData, c);

            RouteData parentRouteData = helper.ViewContext.RouteData;
            RouteData routeData = new RouteData(parentRouteData.Route, parentRouteData.RouteHandler);
            routeData.Values["controller"] = controller;
            routeData.Values["action"] = controller;
            RequestContext rc = new RequestContext(helper.ViewContext.HttpContext, routeData);
            ControllerContext cc = new ControllerContext(rc, c);
            c.ControllerContext = cc;

            MethodInfo mi = c.GetType().GetMethod("Index");
            PartialViewResult result = (PartialViewResult)mi.Invoke(c, new object[] { viewname, sectionid });
            result.ExecuteResult(c.ControllerContext);
            return string.Empty;
        }

        public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, string controller)
        {
            ViewDataDictionary vdd = new ViewDataDictionary(htmlHelper.ViewData);
            vdd.Add("Controller", controller);
            htmlHelper.RenderPartial(partialViewName, vdd);
        }

        public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, string controller, object model)
        {
            ViewDataDictionary vdd = new ViewDataDictionary(model);
            vdd.Add("Controller", controller);
            htmlHelper.RenderPartial(partialViewName, vdd);
        }

        public static string CreateModulePropertyControl(this HtmlHelper htmlHelper, ModuleProperty moduleProperty, string value)
        {
            IDictionary<string, object> htmlAttributes = new Dictionary<string, object>();
            Type propertyType = moduleProperty.GetRealPropertyType();
            //string modulePropertyName = "mp_" + moduleProperty.Name;
            string modulePropertyName = string.Format("moduleproperties[{0}].Value", moduleProperty.Name);
            string result = htmlHelper.Hidden("moduleproperties.Index", moduleProperty.Name) + Environment.NewLine;
            result += htmlHelper.Hidden(string.Format("moduleproperties[{0}].Name", moduleProperty.Name), moduleProperty.Name) + Environment.NewLine;
            if (moduleProperty.IsRequired)
                htmlAttributes.Add("class", "required");
            if (propertyType == typeof(string))
            {
                result += htmlHelper.TextBox(modulePropertyName, value, htmlAttributes);
            }
            else if (propertyType == typeof(Int16) || propertyType == typeof(Int32) || propertyType == typeof(Int64))
            {
                result += htmlHelper.TextBox(modulePropertyName, value, htmlAttributes);
            }
            else if (propertyType == typeof(bool))
            {
                bool ischecked = false;
                bool.TryParse(value, out ischecked);
                result += htmlHelper.CheckBox(modulePropertyName, ischecked, htmlAttributes);
            }
            else if (propertyType.IsEnum)
            {
                IList<string> l = new List<string>();
                for (int i = 0; i < Enum.GetValues(propertyType).Length; i++)
                {
                    string option = Enum.GetName(propertyType, i);
                    l.Add(option);
                }
                SelectList sl = new SelectList(l, value);
                result += htmlHelper.DropDownList(modulePropertyName, sl);
            }
            return result;
        }
    }    
}
